﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TreaShares.Backoffice.DataLayer;
using System.ComponentModel;

namespace TreaShares.Backoffice.Controlers
{
    [DataObjectAttribute(true)]
    public class TransactionManager
    {
        private const string STOCK = "Stock";
        private const string OPTION = "Option";

        public int AddStock(Guid clientId, DateTime transactionDate, int entityId, int counterpartyId,
            string transactionRef, char buySell, DateTime valueDate, int stockId, int quantity,
            float price, float flat, float perShare, float totalFees, float totalConsideration)
        {
            using (TreasharesDataContext db = new TreasharesDataContext())
            {
                var tran = new Transaction()
                {
                    ClientId = clientId,
                    TransactionType = STOCK,
                    TransactionDate = transactionDate,
                    Entity = entityId,
                    Counterparty = counterpartyId,
                    TransactionRef = transactionRef,
                    BuySell = buySell,
                    ValueDate = valueDate,
                    Stock = stockId,
                    Quantity = quantity,
                    Price = price,
                    Flat = flat,
                    PerShare = perShare,
                    TotalFees = totalFees,
                    TotalConsideration = totalConsideration,
                    DateCreated=DateTime.Now
                };
                db.Transactions.InsertOnSubmit(tran);
                db.SubmitChanges();
                return tran.Id;
            }
        }
        public int AddOption(Guid clientId, DateTime transactionDate, int entityId, int counterpartyId,
            string transactionRef, char buySell, DateTime valueDate, DateTime vestingDate, DateTime exerciseDate, int stockId, int quantity,
            float price, float premium, string exerciseType)
        {
            using (TreasharesDataContext db = new TreasharesDataContext())
            {
                var tran = new Transaction()
                {
                    ClientId = clientId,
                    TransactionType = OPTION,
                    TransactionDate = transactionDate,
                    Entity = entityId,
                    Counterparty = counterpartyId,
                    TransactionRef = transactionRef,
                    BuySell = buySell,
                    ValueDate = valueDate,
                    VestingDate = vestingDate,
                    ExerciseDate = exerciseDate,
                    Stock = stockId,
                    Quantity = quantity,
                    Price = price,
                    Premium = premium,
                    ExerciseType = exerciseType,
                    DateCreated = DateTime.Now
                };
                db.Transactions.InsertOnSubmit(tran);
                db.SubmitChanges();
                return tran.Id;
            }
        }
        [DataObjectMethodAttribute(DataObjectMethodType.Select)]
        public List<TransactionsGetResult> Select(string ClientId)
        {
            using (TreasharesDataContext db = new TreasharesDataContext())
            {
                Guid cId = new Guid(ClientId);
                var resutl =db.TransactionsGet(cId).ToList();
                return resutl;
            }
        }
        [DataObjectMethodAttribute(DataObjectMethodType.Select)]
        public void Delete(int id)
        {
            using (TreasharesDataContext db = new TreasharesDataContext())
            {

                db.Transactions.DeleteOnSubmit(db.Transactions.Where(t => t.Id == id).Single());
                db.SubmitChanges();
            }
        }
        public List<StockSummaryPosition> SelectStockSummaryPosition(Guid clientId, DateTime from, DateTime to)
        {
            List<StockSummaryPosition> stockSummaryPositions = new List<StockSummaryPosition>();
            using (TreasharesDataContext db = new TreasharesDataContext())
            {
                var stockTransactions = db.Transactions.Where(t => t.ClientId == clientId).Select(t => t).GroupBy(t => t.Stock);
                foreach (var transactionGrop in stockTransactions)
                {
                    double totalPaid = 0;
                    StockSummaryPosition stockSummaryPosition = new StockSummaryPosition();
                    float daysInterval = (to - from).Days;
                    double optionCount = 0;
                    double weightedAverageTreasuryStock = 0;
                    int overHang = 0;
                    int transactionQuantity = 0;
                    double weightedAverageCost = 0;
                    double weightedAverageTotalCost = 0;
                    int totalBuyShares = 0;
                    foreach (var transaction in transactionGrop.ToList())
                    {
                        transactionQuantity += transaction.Quantity;
                        bool isInRange = transaction.ValueDate >= from && transaction.ValueDate <= to;
                        if (isInRange && transaction.TransactionType == STOCK)
                        {
                            weightedAverageCost += (transaction.BuySell == 'B') ? transaction.Price.Value * transaction.Quantity : 0;
                            weightedAverageTotalCost += (transaction.BuySell == 'B') ? transaction.TotalConsideration.Value : transaction.TotalFees.Value;
                            totalBuyShares += (transaction.BuySell == 'B') ? transaction.Quantity : 0;
                            stockSummaryPosition.Sharesrepurchased += transaction.Quantity;
                            stockSummaryPosition.TotalCost += transaction.TotalConsideration.Value;
                            totalPaid += transaction.Price.Value * transaction.Quantity;
                            weightedAverageTreasuryStock += ((to - transaction.ValueDate.Value).Days / daysInterval) * transaction.Quantity;
                        }
                        else if (transaction.ValueDate < from && transaction.TransactionType == STOCK)
                        {
                            weightedAverageTreasuryStock += transaction.Quantity;
                        }
                        else if (transaction.TransactionType == OPTION)
                        {
                            optionCount += transaction.Quantity;
                            if (transaction.VestingDate.Value > to) 
                            {
                                overHang += transaction.Quantity;
                            }
                        }
                    }
                    int totalPaidUpCapital = 0;
                    double weightedPaidUpCapital = 0;
                    double weightedAverageSharesOutstanding = db.StocksPaidUpCapitals.Where(sp => sp.StockSysId == transactionGrop.Key).ToList().Sum(sp =>
                    {

                        totalPaidUpCapital += sp.PaidUpCapital;
                        if (sp.EffectiveDate <= from)
                        {
                            weightedPaidUpCapital += sp.PaidUpCapital;
                        }
                        else if (sp.EffectiveDate <= to)
                        {
                            weightedPaidUpCapital += (((to - sp.EffectiveDate).Days) / daysInterval) * sp.PaidUpCapital;
                        }

                        return weightedPaidUpCapital;
                    });

                    var stock = db.Stocks.Where(s => s.Id == transactionGrop.Key).Single();
                    stockSummaryPosition.Stock = stock.Code;
                    stockSummaryPosition.Currency = stock.Currency;
                    stockSummaryPosition.GrossBurnRate = stock.IndustryBurnRate;
                    stockSummaryPosition.WeightedAverageTreasuryStock = weightedAverageTreasuryStock;
                    stockSummaryPosition.WeightedPaidUpCapital = weightedPaidUpCapital;
                    stockSummaryPosition.WeightedAverageSharesOutstanding = weightedPaidUpCapital - weightedAverageTreasuryStock;
                    stockSummaryPosition.PaidUpCapital = totalPaidUpCapital;
                    stockSummaryPosition.WeightedAverageCost = Math.Abs(weightedAverageCost) / totalBuyShares;
                    stockSummaryPosition.WeightedAverageTotalCost = Math.Abs(weightedAverageTotalCost) / totalBuyShares; //Math.Abs(stockSummaryPosition.TotalCost) / stockSummaryPosition.Sharesrepurchased;
                    stockSummaryPosition.NetBurnRate = ((Math.Abs(optionCount / stockSummaryPosition.WeightedAverageSharesOutstanding)) * 100).ToString("N");
                    stockSummaryPosition.Overhang = Math.Abs( overHang / (float)transactionQuantity).ToString("N");
                    stockSummaryPositions.Add(stockSummaryPosition);
                }
            }
            return stockSummaryPositions;
        }
        [DataObjectMethodAttribute(DataObjectMethodType.Select)]
        public Transaction GetTransaction(int transactionId)
        {
            using (TreasharesDataContext db = new TreasharesDataContext())
            {
                Transaction transaction = db.Transactions.FirstOrDefault(t => t.Id == transactionId);
                return transaction;
            }
        }
    }
    public class StockSummaryPosition
    {
        public string Stock { get; set; }
        public int StockId { get; set; }
        public int Sharesrepurchased { get; set; }
        public string Currency { get; set; }
        public double? WeightedAverageCost { get; set; }
        public double? WeightedAverageTotalCost { get; set; }
        public double TotalCost { get; set; }
        public int? PaidUpCapital { get; set; }

        public double? GrossBurnRate { get; set; }
        public string NetBurnRate { get; set; }
        public string  Overhang { get; set; }
        public double WeightedAverageTreasuryStock { get; set; }
        public double WeightedPaidUpCapital { get; set; }
        public double WeightedAverageSharesOutstanding { get; set; }
    }
}